#include <QtGui>
#include <math.h>
#include "psglscene.h"
#include "glext.h"
#include "psgl_draw_utils.h"
#include "psglobject.h"
#include "psglmodel.h"


GLint viewport[4];

PSGLScene::PSGLScene(QWidget* parent) 
  : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
  , m_drawPlanet(true)
  , m_drawTrajectory(true)
  , m_drawText(true)
{

   //timer = new QTimer(this);
   //connect(timer, SIGNAL(timeout()), this, SLOT(change()));
   //timer->start(10);

   glModel = PSGLModel();

   QGLFormat frmt;
   frmt.setSwapInterval(1);
   setFormat(frmt);
}

PSGLScene::~PSGLScene()
{

}

void PSGLScene::initializeGL()
{
   xRot=-90; yRot=0; zRot=0; xTra = 0, yTra = 0, zTra=0; nSca=1;
   frameNumber = 0;
   trackNumber = -1; 

   qglClearColor(Qt::black);
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_CULL_FACE);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_MULTISAMPLE);

   initializeMeshes();

   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

void PSGLScene::resizeGL(int nWidth, int nHeight)
{
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();

   ratio=(GLfloat)nHeight/(GLfloat)nWidth;

   if (nWidth>=nHeight)
      glOrtho(-2.0/ratio, 2.0/ratio, -2.0, 2.0, -10.0, 10.0);
   else
      glOrtho(-2.0, 2.0, -2.0*ratio, 2.0*ratio, -10.0, 10.0);

   glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
   glGetIntegerv(GL_VIEWPORT, viewport);
}

void PSGLScene::paintGL()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   trackObject(trackNumber);

   glScalef(nSca, nSca, nSca);
   glTranslatef(xTra, zTra, 0);
   glRotatef(xRot, 1.0f, 0.0f, 0.0f);
   glRotatef(yRot, 0.0f, 1.0f, 0.0f);
   glRotatef(zRot, 0.0f, 0.0f, 1.0f);

   glModel.renderFrame(frameNumber, m_drawPlanet, m_drawTrajectory, m_drawText);

  
   drawAxes();
}

void PSGLScene::mousePressEvent(QMouseEvent* pe)
{
   ptrMousePosition = pe->pos();
}

void PSGLScene::mouseReleaseEvent(QMouseEvent* pe)
{

}

void PSGLScene::mouseMoveEvent(QMouseEvent* pe)
{
   xRot += 180/nSca*(GLfloat)(pe->y()-ptrMousePosition.y())/height();
   zRot += 180/nSca*(GLfloat)(pe->x()-ptrMousePosition.x())/width();

   ptrMousePosition = pe->pos();

   updateGL();
}

void PSGLScene::wheelEvent(QWheelEvent* pe)
{
   if ((pe->delta())>0) scale_plus(); else if ((pe->delta())<0) scale_minus();

   updateGL();
}


void PSGLScene::keyPressEvent(QKeyEvent* pe)
{
   switch (pe->key())
   {
      case Qt::Key_Plus:
         scale_plus();
      break;

      case Qt::Key_Equal:
         scale_plus();
      break;

      case Qt::Key_Minus:
         scale_minus();
      break;

      case Qt::Key_Up:
         rotate_up();
      break;

      case Qt::Key_Down:
         rotate_down();
      break;

      case Qt::Key_Left:
        rotate_left();
      break;

      case Qt::Key_Right:
         rotate_right();
      break;

      case Qt::Key_Z:
         translate_down();
      break;

      case Qt::Key_X:
         translate_up();
      break;

      case Qt::Key_A:
         translate_left();
      break;

      case Qt::Key_D:
         translate_right();
      break;


      case Qt::Key_Space:
         defaultScene();
      break;

      case Qt::Key_Escape:
         this->close();
      break;
   }

   updateGL();
}

void PSGLScene::scale_plus()
{
   nSca = nSca*1.1;
}

void PSGLScene::scale_minus()
{
   nSca = nSca/1.1;
}

void PSGLScene::rotate_up()
{
   xRot += 1.0;
}

void PSGLScene::rotate_down()
{
   xRot -= 1.0;
}

void PSGLScene::rotate_left()
{
   zRot += 1.0;
}

void PSGLScene::rotate_right()
{
   zRot -= 1.0;
}

void PSGLScene::translate_down()
{
   zTra -= 0.05;
}

void PSGLScene::translate_up()
{
   zTra += 0.05;
}

void PSGLScene::translate_left()
{
   xTra -= 0.05;
}

void PSGLScene::translate_right()
{
   xTra += 0.05;
}



void PSGLScene::defaultScene()
{
   xRot=-90; yRot=0; zRot=0; xTra = 0; yTra = 0, zTra=0; nSca=1;
   frameNumber = 0;
   updateGL();
}
void PSGLScene::selectFigures(QPoint mp)
{
}

void PSGLScene::drawAxes()
{
  glPushMatrix();

  GLint h = this->height();
  GLint w = this->width();
   
  //glTranslatef((GLfloat)(w)*0.001, 0,  (GLfloat)(h)*0.001);


   glLineWidth(1.0f);

   glColor4f(1.00f, 1.00f, 1.00f, 1.0f);
   glBegin(GL_LINES);
      glVertex3f( 2.0f,  0.0f,  0.0f);
      glVertex3f(-2.0f,  0.0f,  0.0f);
   glEnd();

   drawText(2.3, 0.0, 0.0, "x");

   glBegin(GL_LINES);
      glVertex3f( 0.0f,  2.0f,  0.0f);
      glVertex3f( 0.0f, -2.0f,  0.0f);
   glEnd();
    drawText(0.0, 2.3, 0.0, "y");

   glBegin(GL_LINES);
      glVertex3f( 0.0f,  0.0f,  2.0f);
      glVertex3f( 0.0f,  0.0f, -2.0f);
   glEnd();

    drawText(0.0, 0.0, 2.3, "z");

    glPopMatrix();
}
void PSGLScene::changeFrame(int n)
{
  if (n < glModel.objects[0].trajectory.size())
  frameNumber = n;

  updateGL();
}

void PSGLScene::drawPlanet(int drawFlag)
{
  if (drawFlag != 0)
    m_drawPlanet = true;
  else
    m_drawPlanet = false;
  updateGL();
}
void PSGLScene::drawTrajectory(int drawFlag)
{
  if (drawFlag != 0)
    m_drawTrajectory = true;
  else
    m_drawTrajectory = false;
  updateGL();
}
void PSGLScene::drawCaption(int drawFlag)
{
  if (drawFlag != 0)
    m_drawText = true;
  else
    m_drawText = false;
  updateGL();
}

void PSGLScene::trackObject(int trackID)
{
  if (trackID = -1)
    return;
  else
  {
    xTra = glModel.objects[trackID].trajectory[frameNumber].x -5*nSca;
    yTra = glModel.objects[trackID].trajectory[frameNumber].y -5*nSca;
    zTra = glModel.objects[trackID].trajectory[frameNumber].z -5*nSca;
  }
}

void PSGLScene::changeTracking(int n)
{
  trackNumber = n;
  updateGL();
}
